package sentinel.demo.controller;


import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.context.Context;
import com.alibaba.csp.sentinel.context.ContextUtil;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PostConstruct;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@RestController
@RequestMapping("/test")
public class TestController {

    @PostConstruct
    public void initFlowRules() {
        //1.创建存放限流规则的集合
        List<FlowRule> rules = new ArrayList<>();
        //2.创建限流规则
        FlowRule rule = new FlowRule();
        //定义资源，表示sentinel会对这个资源生效
        rule.setResource("helloSentinel");
        //定义限流规则类型
        rule.setGrade(RuleConstant.FLOW_GRADE_THREAD);

        //定义QPS每秒能通过的请求个数
        rule.setCount(1);
        //3.将限流规则放入集合中
        rules.add(rule);
        //4.加载限流规则
        FlowRuleManager.loadRules(rules);
    }


    @GetMapping("/sayHello")
    public String sayHello(String name) {
        try (Entry entry = SphU.entry("test")) {
//            Thread.sleep(1000);
            System.out.println(Thread.currentThread().getName() + "----hello world" + LocalDateTime.now());
            System.out.println("=================================================================");
        } catch (BlockException e) {
            e.printStackTrace();
//        } catch (InterruptedException e) {
//            throw new RuntimeException(e);
        }
        return "Hello World " + name;
    }

    @GetMapping("/helloSentinel")
    public String hello() {
        try (Entry entry = SphU.entry("helloSentinel")) {

            System.out.println(Thread.currentThread().getName() + ":::::::helloSentinel success." + System.currentTimeMillis());
//            Thread.sleep(500);
            return "helloSentinel success.";
        } catch (Exception e) {
            System.out.println("helloSentinel error.");
            return "helloSentinel error";
        }
    }


    public Set<Thread> set = new HashSet<>();

    @GetMapping("/test2")
    public Object test2() {
        Thread thread = Thread.currentThread();
        set.add(thread);
        System.out.println(set.size());
        return thread.toString();
    }

//=============================================================================

    @SentinelResource(value = "test")
    @GetMapping("/test")
    public void test() {
        System.out.println("Test");
    }

    @SentinelResource(value = "hello", fallback = "helloFallback")
    public String hello(long s) {
        if (s < 0) {
            throw new IllegalArgumentException("invalid arg");
        }
        return String.format("Hello at %d", s);
    }

    @SentinelResource(value = "helloAnother", defaultFallback = "defaultFallback",
            exceptionsToIgnore = {IllegalStateException.class})
    public String helloAnother(String name) {
        if (name == null || "bad".equals(name)) {
            throw new IllegalArgumentException("oops");
        }
        if ("foo".equals(name)) {
            throw new IllegalStateException("oops");
        }
        return "Hello, " + name;
    }

    public String helloFallback(long s, Throwable ex) {
        // Do some log here.
        ex.printStackTrace();
        return "Oops, error occurred at " + s;
    }

    public String defaultFallback() {
        System.out.println("Go to default fallback");
        return "default_fallback";
    }
}
